package com.career.syn.util;

import com.career.syn.constant.Constant;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 
 * @ClassName: CommonUtil
 * @Description: 通用工具类
 * @author georgeli
 * @date 2017年11月29日 上午8:09:02
 */
@SuppressWarnings("restriction")
public class CommonUtil {

	/**
	 * 
	 * @Title: getStandardRequestString @Description: 构造规范化请求串 @author
	 *         georgeli @date 2017年11月29日 上午8:08:56 @param param @return
	 *         String @throws
	 */
	public static String getStandardRequestString(Map<String, String> params) {
		String[] keys = new String[params.size()];
		int point = 0;
		for (Map.Entry<String, String> entry : params.entrySet()) {
			keys[point++] = entry.getKey();
		}
		// 对key按照字典序排序
		Arrays.sort(keys);
		String param_str = "";
		try {
			for (int i = 0; i < keys.length; i++) {
				param_str += (keys[i] + "=" + percentEncode(params.get(keys[i])));
				if (i + 1 < keys.length)
					param_str += "&";
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return param_str;
	}

	public static String percentEncode(String value) throws UnsupportedEncodingException {
		return value != null ? URLEncoder.encode(value, Constant.ENCODING).replace("+", "%20").replace("*", "%2A")
				.replace("%7E", "~") : null;
	}

	/**
	 * @throws UnsupportedEncodingException 
	 * 
	* @Title: ReadAsChars
	* @Description: 字符串读取
	* @author georgeli
	* @date 2018年11月29日 下午5:52:44
	* @param request
	* @return String
	* @throws
	 */
	public static String ReadAsChars(HttpServletRequest request) throws UnsupportedEncodingException {
		request.setCharacterEncoding("utf8");
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder("");
		try {
			br = request.getReader();
			String str;
			while ((str = br.readLine()) != null) {
				sb.append(str);
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (null != br) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 将流转换为字符串
	 *
	 * @param is
	 * @return
	 * @throws IOException
	 * @throws NoSuchAlgorithmException
	 */
	public static String readStreamAsStr(HttpServletRequest request) throws IOException, NoSuchAlgorithmException {
		String data = ReadAsChars(request);
		byte[] input = data.getBytes(java.nio.charset.Charset.forName("utf-8"));
		MessageDigest messageDigest = MessageDigest.getInstance("MD5");
		messageDigest.update(input);
		byte[] md5Bytes = messageDigest.digest();
		BASE64Encoder b64Encoder = new BASE64Encoder();
		return b64Encoder.encode(md5Bytes);
	}

	/**
	 * 
	 * @Title: generateApiKey @Description: 生成apiKey @author georgeli @date
	 *         2017年11月29日 上午8:08:39 @return String @throws
	 */
	public static String generateApiKey() {
		BASE64Encoder b64Encoder = new BASE64Encoder();
		return b64Encoder
				.encode(MD5Util.md5Base64(UUID.randomUUID().toString() + System.currentTimeMillis()).getBytes())
				.substring(0, 16);
	}

	/**
	 * 
	 * @Title: generateSecretKey @Description: 生成secretKey @author
	 *         georgeli @date 2017年11月29日 上午8:09:14 @return String @throws
	 */
	public static String generateSecretKey() {
		BASE64Encoder b64Encoder = new BASE64Encoder();
		return b64Encoder
				.encode(MD5Util.md5Base64(UUID.randomUUID().toString() + System.currentTimeMillis()).getBytes())
				.substring(0, 30);
	}

	/**
	 * 
	 * @Title: generateAccessToken @Description: 生成accessToken @author
	 *         georgeli @date 2017年11月29日 上午8:09:32 @param username @return
	 *         String @throws
	 */
	public static String generateAccessToken(String username) {
		int rand = (int) (Math.random() * (9999 - 1000 + 1)) + 1000;
		String nonce = System.currentTimeMillis() + String.valueOf(rand);
		return MD5Util.md5(username).substring(0, 6) + MD5Util.md5(nonce);
	}

	/**
	 * 生成盐
	 * 
	 * @return
	 */
	public static String createSalt() {
		int rand = new Random().nextInt(100) + 1;
		String salt = UUID.randomUUID().toString() + rand;
		return MD5Util.md5Base64(salt).substring(0, 8);
	}

	/**
	 * 加密
	 * 
	 * @param password
	 * @param salt
	 * @return
	 */
	public static String digest(String password, String salt) {
		return MD5Util.md5(MD5Util.md5(password) + salt);
	}

	/**
	 * 
	 * @Title: generateCookiesId @Description: 生成cookiesId @author
	 *         georgeli @date 2017年11月29日 上午9:41:22 @return String @throws
	 */
	public static String generateCookiesId() {
		int rand = (int) (Math.random() * (9999 - 1000 + 1)) + 1000;
		String nonce = System.currentTimeMillis() + String.valueOf(rand);
		return MD5Util.md5Base64(UUID.randomUUID().toString() + nonce);
	}

	/**
	 * 
	 * @Title: generateNonce @Description: 生成Nonce @author georgeli @date
	 *         2017年11月29日 上午10:03:06 @param timestamp @return String @throws
	 */
	public static String generateNonce(String timestamp) {
		int rand = (int) (Math.random() * (9999 - 1000 + 1)) + 1000;
		String nonce = timestamp + String.valueOf(rand);
		return MD5Util.md5(nonce);
	}

	/**
	 * 
	 * @Title: generateRequestId @Description: 生成requestId @author
	 *         georgeli @date 2018年2月7日 下午7:24:30 @return String @throws
	 */
	public static String generateRequestId() {
		return UUID.randomUUID().toString();
	}

	/**
	 * 
	 * @Title: UUID @Description: 生成UUID @author georgeli @date 2018年2月7日
	 *         下午7:24:47 @param name @return String @throws
	 */
	public static String UUID(String name) {
		try {
			return UUID.nameUUIDFromBytes(name.getBytes("UTF-8")).toString().replaceAll("-", "");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return UUID.nameUUIDFromBytes(name.getBytes()).toString().replaceAll("-", "");
		}
	}

	/**
	 * 
	 * @Title: UUID @Description: 生成UUID @author georgeli @date 2018年2月7日
	 *         下午7:25:04 @return String @throws
	 */
	public static String UUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 
	 * @Title: joinHostPort @Description: host port连接 @author georgeli @date
	 *         2018年2月7日 下午7:25:21 @param hostList @param port @return
	 *         String @throws
	 */
	public static String joinHostPort(String hostList, String port) {
		String result = "";

		String[] hostArr = hostList.split(",");
		for (int i = 0; i < hostArr.length; i++) {
			result += hostArr[i] + ":" + port;
			if (i != (hostArr.length - 1)) {
				result += ",";
			}
		}

		return result;
	}

	/**
	 * 
	 * @Title: strToList @Description: string转list @author georgeli @date
	 *         2018年2月7日 下午7:25:38 @param str @return List<String> @throws
	 */
	public static List<String> strToList(String str) {
		List<String> result = new ArrayList<String>();
		String[] strArr = str.split(",");

		for (int i = 0; i < strArr.length; i++) {
			result.add(strArr[i]);
		}

		return result;
	}

	public static void main(String[] args) throws Exception {
		// 请求的参数列表
		String now = String.valueOf(System.currentTimeMillis());
		Map<String, String> params = new HashMap<String, String>();

		params.put("apiKey", "aytJZWFlRk1FM2Q1");
		params.put("timestamp", now);
		params.put("nonce", generateNonce(now));
		params.put("signatureMethod", "HMACSHA256");

		String content = "{\"publicip\":{\"ip_version\":6}}";
		byte[] input = content.getBytes(java.nio.charset.Charset.forName("utf-8"));
		MessageDigest messageDigest = MessageDigest.getInstance("MD5");
		messageDigest.update(input);
		byte[] md5Bytes = messageDigest.digest();
		BASE64Encoder b64Encoder = new BASE64Encoder();
		String contentMD5 = b64Encoder.encode(md5Bytes);
		System.out.println("contentMD5: " + contentMD5);
		String BuildRequestParameters = CommonUtil.percentEncode(CommonUtil.getStandardRequestString(params));
		System.out.println("BuildRequestParameters : " + BuildRequestParameters);

		StringBuilder sb = new StringBuilder();
		sb.append("POST" + Constant.PARAM_CONNECTOR);
		sb.append(contentMD5 + Constant.PARAM_CONNECTOR);
		sb.append(BuildRequestParameters);

		String sign = HmacShaUtil.calculateRFC2104HMAC("aXFIb2Z1VmIraWJOQlN2c3l6L2dvdz", sb.toString(), "HMACSHA256");
		System.out.println("sign:" + sign);
	}

}